Process的使用 |
您所在的位置:网站首页 › java process 进程交互 › Process的使用 |
前言
目前需要做一个功能,就是通过java进行mysqldump备份,但是mysql时运行在容器中的时候, 已知Java目前只有一个Runtime.getRuntime()一种方式能获得当前linux运行时环境的方式 所以接下来就是通过这个方式实现这个功能 遇到的问题一:process.waitFor()一直阻塞不返回代码: 下面是实现代码: public void backup(HttpServletResponse reponse){ BufferedReader reader; try{ String cmdStr = "docker exec mysql sh -c 'mysqldump -h 127.0.0.1 -uroot -p123456 database --ser-charset=UTF-8'"; // 回去结果 int exitCode=process.waitFor(); Process exec = Runtime.getRuntime.exec(cmdStr); reader=new BufferedReader(new InputStreamReader(process.getInputStream())); String line=null; while((line=reader.readLine())!=null){ System.out.println(line); } if (exitCode != 0){ log.error("错误") } } }原因: process.waitFor()方法和exitValue()方法很像, 但是exitValue()是直接获得一个返回结果,但是有可能命令还在执行中,因此结果不一定正确; 而waitFor()方法是等待进程结束后才会有返回值。 因此waitfor方法是会被阻塞的,同时因为因为输入和输出流提供有限的缓冲区大小,如果读写子进程的输出流或输入流出现失败,当缓冲区满之后将无法继续写入数据,则可能导致子进程阻塞 因此我们需要不断的将缓冲区的内容读取出来就了以防止阻塞,所以process.waitFor()应该换个位置 改进代码如下: public void backup(HttpServletResponse reponse){ BufferedReader reader; try{ String cmdStr = "docker exec mysql sh -c 'mysqldump -h 127.0.0.1 -uroot -p123456 database --ser-charset=UTF-8'"; Process exec = Runtime.getRuntime.exec(cmdStr); reader=new BufferedReader(new InputStreamReader(process.getInputStream())); String line=null; while((line=reader.readLine())!=null){ System.out.println(line); } // 回去结果 int exitCode=process.waitFor(); if (exitCode != 0){ log.error("错误") } } } 遇到的问题二:process.waitFor()返回值为127查明原因127对应的应该是没有环境导致的, 因此在使用Process 的过程中推荐使用绝对路径,就算docker也一样 代码改进如下: public void backup(HttpServletResponse reponse){ BufferedReader reader; try{ String cmdStr = "/usr/bin/docker exec mysql sh -c 'mysqldump -h 127.0.0.1 -uroot -p123456 database --ser-charset=UTF-8'"; Process exec = Runtime.getRuntime.exec(cmdStr); reader=new BufferedReader(new InputStreamReader(process.getInputStream())); String line=null; while((line=reader.readLine())!=null){ System.out.println(line); } // 回去结果 int exitCode=process.waitFor(); if (exitCode != 0){ log.error("错误") } } } 遇到的问题三:process.waitFor()返回值为1返回值为1的原因大概是因为执行的语句有问题,但是我将该语句放到linux环境中执行却能过得到正常结果 后面简单的百度一下并且看了一下源码: 发现Runtime.exec()是存在两种字符参数的 分别是: 1、Runtime.exec(String command)2、Runtime.exec(String[] cmdarray)但是第1种方法的本质是Runtime.exec(command.split(" ")) 看下代码,可以见到我们通过linux执行docker命令,在通过docker 执行容器命令,简单的空格已经不能支持这么复杂的逻辑了,其实一些包含特殊字符的也不能进行执行,所以我们需要使用第二种方式,手动将命令分层 改进代码如下: public void backup(HttpServletResponse reponse){ BufferedReader reader; try{ //String cmdStr = " mysqldump -h 127.0.0.1 -uroot -p123456 database --ser-charset=UTF-8"; //String cmdStr = "docker exec mysql sh -c 'mysqldump -h 127.0.0.1 -uroot -p123456 database --ser-charset=UTF-8'"; String[] cmdStr = {"/usr/bin/docker","exec","mysql","sh","-c","/usr/bin/mysqldump -h 127.0.0.1 -uroot -p123456 database --ser-charset=UTF-8"} Process exec = Runtime.getRuntime.exec(cmdStr); reader=new BufferedReader(new InputStreamReader(process.getInputStream())); String line=null; while((line=reader.readLine())!=null){ System.out.println(line); } int exitCode=process.waitFor(); if (exitCode != 0){ log.error("错误") } } } |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |